// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
/*
 * Physical memory map
 *
 * Copyright 2017-2019 IBM Corp.
 */

#include <phys-map.h>
#include <chip.h>
#include <skiboot.h>
#include <opal-api.h>
#include <stack.h>
#include <inttypes.h>

struct phys_map_entry {
	enum phys_map_type type;
	int index;
	uint64_t addr;
	uint64_t size;
};

struct phys_map_info {
	int chip_select_shift;
	const struct phys_map_entry *table;
};

static const struct phys_map_info *phys_map;

static const struct phys_map_entry phys_map_table_nimbus[] = {

	/* System memory upto 4TB minus GPU memory */
	{ SYSTEM_MEM,      0, 0x0000000000000000ull, 0x0000034000000000ull },
	/* GPU memory from 4TB - 128GB*GPU */
	{ GPU_MEM_4T_DOWN, 5, 0x0000034000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 4, 0x0000036000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 3, 0x0000038000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 2, 0x000003a000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 1, 0x000003c000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 0, 0x000003e000000000ull, 0x0000002000000000ull },
	/* GPU memory from 4TB + 128GB*GPU. 4 GPUs only */
	{ GPU_MEM_4T_UP,   0, 0x0000040000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_UP,   1, 0x0000042000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_UP,   2, 0x0000044000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_UP,   3, 0x0000046000000000ull, 0x0000002000000000ull },

	/*
	 * OpenCAPI LPC Memory
	 *
	 * With chip address extension enabled, we allocate 4TB ranges
	 * (in the second non-mirrored region) for each OpenCAPI link
	 * by varying the upper 2 bits of the group ID.
	 *
	 * We don't currently support >4TB ranges.
	 */
	{ OCAPI_MEM,	   0, 0x0002000000000000ull, 0x0000040000000000ull },
	{ OCAPI_MEM,	   1, 0x0002200000000000ull, 0x0000040000000000ull },
	{ OCAPI_MEM,	   2, 0x0002400000000000ull, 0x0000040000000000ull },
	{ OCAPI_MEM,	   3, 0x0002600000000000ull, 0x0000040000000000ull },

	/* 0 TB offset @ MMIO 0x0006000000000000ull */
	{ PHB4_64BIT_MMIO, 0, 0x0006000000000000ull, 0x0000004000000000ull },
	{ PHB4_64BIT_MMIO, 1, 0x0006004000000000ull, 0x0000004000000000ull },
	{ PHB4_64BIT_MMIO, 2, 0x0006008000000000ull, 0x0000004000000000ull },
	{ PHB4_32BIT_MMIO, 0, 0x000600c000000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 1, 0x000600c080000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 2, 0x000600c100000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 3, 0x000600c180000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 4, 0x000600c200000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 5, 0x000600c280000000ull, 0x0000000080000000ull },
	{ PHB4_XIVE_ESB  , 0, 0x000600c300000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB  , 1, 0x000600c320000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB  , 2, 0x000600c340000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB  , 3, 0x000600c360000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB  , 4, 0x000600c380000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB  , 5, 0x000600c3a0000000ull, 0x0000000020000000ull },
	{ PHB4_REG_SPC   , 0, 0x000600c3c0000000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC   , 1, 0x000600c3c0100000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC   , 2, 0x000600c3c0200000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC   , 3, 0x000600c3c0300000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC   , 4, 0x000600c3c0400000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC   , 5, 0x000600c3c0500000ull, 0x0000000000100000ull },
	{ RESV	         , 0, 0x000600c3c0600000ull, 0x0000000c3fa00000ull },
	{ NPU_OCAPI_MMIO , 0, 0x000600d000000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO , 1, 0x000600d800000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO , 2, 0x000600e000000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO , 3, 0x000600e800000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO , 4, 0x000600f000000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO , 5, 0x000600f800000000ull, 0x0000000800000000ull },

	/* 1 TB offset @ MMIO 0x0006000000000000ull */
	{ XIVE_VC        , 0, 0x0006010000000000ull, 0x0000008000000000ull },
	{ XIVE_PC        , 0, 0x0006018000000000ull, 0x0000001000000000ull },
	{ VAS_USER_WIN   , 0, 0x0006019000000000ull, 0x0000000100000000ull },
	{ VAS_HYP_WIN    , 0, 0x0006019100000000ull, 0x0000000002000000ull },
	{ RESV	         , 1, 0x0006019102000000ull, 0x000000001e000000ull },
	{ OCAB_XIVE_ESB  , 0, 0x0006019120000000ull, 0x0000000020000000ull },
	{ RESV	         , 3, 0x0006019140000000ull, 0x0000006ec0000000ull },

	/* 2 TB offset @ MMIO 0x0006000000000000ull */
	{ PHB4_64BIT_MMIO, 3, 0x0006020000000000ull, 0x0000004000000000ull },
	{ PHB4_64BIT_MMIO, 4, 0x0006024000000000ull, 0x0000004000000000ull },
	{ PHB4_64BIT_MMIO, 5, 0x0006028000000000ull, 0x0000004000000000ull },
	{ RESV	         , 4, 0x000602c000000000ull, 0x0000004000000000ull },

	/* 3 TB offset @ MMIO 0x0006000000000000ull */
	{ LPC_BUS        , 0, 0x0006030000000000ull, 0x0000000100000000ull },
	{ FSP_MMIO       , 0, 0x0006030100000000ull, 0x0000000100000000ull },
	{ NPU_REGS       , 0, 0x0006030200000000ull, 0x0000000001000000ull },
	{ NPU_USR        , 0, 0x0006030201000000ull, 0x0000000000200000ull },
	{ NPU_PHY        , 0, 0x0006030201200000ull, 0x0000000000200000ull },
	{ NPU_PHY	 , 1, 0x0006030201400000ull, 0x0000000000200000ull },
	{ NPU_NTL	 , 0, 0x0006030201600000ull, 0x0000000000020000ull },
	{ NPU_NTL	 , 1, 0x0006030201620000ull, 0x0000000000020000ull },
	{ NPU_NTL	 , 2, 0x0006030201640000ull, 0x0000000000020000ull },
	{ NPU_NTL	 , 3, 0x0006030201660000ull, 0x0000000000020000ull },
	{ NPU_NTL	 , 4, 0x0006030201680000ull, 0x0000000000020000ull },
	{ NPU_NTL	 , 5, 0x00060302016a0000ull, 0x0000000000020000ull },
	{ NPU_GENID	 , 0, 0x00060302016c0000ull, 0x0000000000020000ull },
	{ NPU_GENID	 , 1, 0x00060302016e0000ull, 0x0000000000020000ull },
	{ NPU_GENID	 , 2, 0x0006030201700000ull, 0x0000000000020000ull },
	{ RESV	         , 5, 0x0006030201720000ull, 0x00000000018e0000ull },
	{ PSIHB_REG      , 0, 0x0006030203000000ull, 0x0000000000100000ull },
	{ XIVE_IC        , 0, 0x0006030203100000ull, 0x0000000000080000ull },
	{ XIVE_TM        , 0, 0x0006030203180000ull, 0x0000000000040000ull },
	{ PSIHB_ESB      , 0, 0x00060302031c0000ull, 0x0000000000010000ull },
	{ NX_RNG         , 0, 0x00060302031d0000ull, 0x0000000000010000ull },
	{ RESV           , 6, 0x00060302031e0000ull, 0x000000001ce20000ull },
	{ CENTAUR_SCOM   , 0, 0x0006030220000000ull, 0x0000000020000000ull },
	{ RESV           , 7, 0x0006030240000000ull, 0x000000f9c0000000ull },
	{ XSCOM          , 0, 0x000603fc00000000ull, 0x0000000400000000ull },

	/* NULL entry at end */
	{ NULL_MAP, 0, 0, 0 },
};

static const struct phys_map_info phys_map_nimbus = {
	.chip_select_shift = 42,
	.table = phys_map_table_nimbus,
};

static const struct phys_map_entry phys_map_table_axone[] = {

	/* System memory up to 4TB minus GPU memory */
	{ SYSTEM_MEM,      0, 0x0000000000000000ull, 0x0000034000000000ull },
	/* GPU memory from 4TB - 128GB*GPU */
	{ GPU_MEM_4T_DOWN, 5, 0x0000034000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 4, 0x0000036000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 3, 0x0000038000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 2, 0x000003a000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 1, 0x000003c000000000ull, 0x0000002000000000ull },
	{ GPU_MEM_4T_DOWN, 0, 0x000003e000000000ull, 0x0000002000000000ull },

	/* 0 TB offset @ MMIO 0x0006000000000000ull */
	{ PHB4_64BIT_MMIO, 0, 0x0006000000000000ull, 0x0000004000000000ull },
	{ PHB4_64BIT_MMIO, 1, 0x0006004000000000ull, 0x0000004000000000ull },
	{ PHB4_64BIT_MMIO, 2, 0x0006008000000000ull, 0x0000004000000000ull },
	{ PHB4_32BIT_MMIO, 0, 0x000600c000000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 1, 0x000600c080000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 2, 0x000600c100000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 3, 0x000600c180000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 4, 0x000600c200000000ull, 0x0000000080000000ull },
	{ PHB4_32BIT_MMIO, 5, 0x000600c280000000ull, 0x0000000080000000ull },
	{ PHB4_XIVE_ESB,   0, 0x000600c300000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB,   1, 0x000600c320000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB,   2, 0x000600c340000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB,   3, 0x000600c360000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB,   4, 0x000600c380000000ull, 0x0000000020000000ull },
	{ PHB4_XIVE_ESB,   5, 0x000600c3a0000000ull, 0x0000000020000000ull },
	{ PHB4_REG_SPC,    0, 0x000600c3c0000000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC,    1, 0x000600c3c0100000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC,    2, 0x000600c3c0200000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC,    3, 0x000600c3c0300000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC,    4, 0x000600c3c0400000ull, 0x0000000000100000ull },
	{ PHB4_REG_SPC,    5, 0x000600c3c0500000ull, 0x0000000000100000ull },
	{ RESV,            0, 0x000600c3c0600000ull, 0x0000000c3fa00000ull },
	{ NPU_OCAPI_MMIO,  0, 0x000600d000000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO,  1, 0x000600d800000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO,  2, 0x000600e000000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO,  3, 0x000600e800000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO,  4, 0x000600f000000000ull, 0x0000000800000000ull },
	{ NPU_OCAPI_MMIO,  5, 0x000600f800000000ull, 0x0000000800000000ull },

	/* 1 TB offset @ MMIO 0x0006000000000000ull */
	{ XIVE_VC,         0, 0x0006010000000000ull, 0x0000008000000000ull },
	{ XIVE_PC,         0, 0x0006018000000000ull, 0x0000004000000000ull },
	{ VAS_USER_WIN,    0, 0x000601c000000000ull, 0x0000000100000000ull },
	{ VAS_HYP_WIN,     0, 0x000601c100000000ull, 0x0000000002000000ull },
	{ RESV,            1, 0x000601c102000000ull, 0x0000003efe000000ull },

	/* 2 TB offset @ MMIO 0x0006000000000000ull */
	{ PHB4_64BIT_MMIO, 3, 0x0006020000000000ull, 0x0000004000000000ull },
	{ PHB4_64BIT_MMIO, 4, 0x0006024000000000ull, 0x0000004000000000ull },
	{ PHB4_64BIT_MMIO, 5, 0x0006028000000000ull, 0x0000004000000000ull },
	{ RESV,            2, 0x000602c000000000ull, 0x0000004000000000ull },

	/* 3 TB offset @ MMIO 0x0006000000000000ull */
	{ LPC_BUS,         0, 0x0006030000000000ull, 0x0000000100000000ull },
	{ FSP_MMIO,        0, 0x0006030100000000ull, 0x0000000100000000ull },
	{ RESV,            3, 0x0006030200000000ull, 0x0000000003000000ull },
	{ PSIHB_REG,       0, 0x0006030203000000ull, 0x0000000000100000ull },
	{ XIVE_IC,         0, 0x0006030203100000ull, 0x0000000000080000ull },
	{ XIVE_TM,         0, 0x0006030203180000ull, 0x0000000000040000ull },
	{ PSIHB_ESB,       0, 0x00060302031c0000ull, 0x0000000000010000ull },
	{ NX_RNG,          0, 0x00060302031d0000ull, 0x0000000000010000ull },
	{ RESV,            4, 0x00060302031e0000ull, 0x00000001fce20000ull },
	{ MC_OCMB_CFG,     0, 0x0006030400000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     1, 0x0006030480000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    0, 0x0006030500000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    1, 0x0006030580000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     2, 0x0006030600000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     3, 0x0006030680000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    2, 0x0006030700000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    3, 0x0006030780000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     4, 0x0006030800000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     5, 0x0006030880000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    4, 0x0006030900000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    5, 0x0006030980000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     6, 0x0006030a00000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     7, 0x0006030a80000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    6, 0x0006030b00000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    7, 0x0006030b80000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     8, 0x0006030c00000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,     9, 0x0006030c80000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    8, 0x0006030d00000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,    9, 0x0006030d80000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,    10, 0x0006030e00000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,    11, 0x0006030e80000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,   10, 0x0006030f00000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,   11, 0x0006030f80000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,    12, 0x0006031000000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,    13, 0x0006031080000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,   12, 0x0006031100000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,   13, 0x0006031180000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,    14, 0x0006031200000000ull, 0x0000000080000000ull },
	{ MC_OCMB_CFG,    15, 0x0006031280000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,   14, 0x0006031300000000ull, 0x0000000080000000ull },
	{ MC_OCMB_MMIO,   15, 0x0006031380000000ull, 0x0000000080000000ull },
	{ RESV,            5, 0x0006031400000000ull, 0x000000d800000000ull },
	{ NPU_REGS,        0, 0x000603ec00000000ull, 0x0000000001000000ull },
	{ NPU_REGS,        1, 0x000603ec01000000ull, 0x0000000001000000ull },
	{ NPU_REGS,        2, 0x000603ec02000000ull, 0x0000000001000000ull },
	{ NPU_NTL,         0, 0x000603ec03000000ull, 0x0000000000020000ull },
	{ NPU_NTL,         1, 0x000603ec03020000ull, 0x0000000000020000ull },
	{ NPU_NTL,         2, 0x000603ec03040000ull, 0x0000000000020000ull },
	{ NPU_NTL,         3, 0x000603ec03060000ull, 0x0000000000020000ull },
	{ NPU_GENID,       0, 0x000603ec03080000ull, 0x0000000000080000ull },
	{ NPU_NTL,         4, 0x000603ec03100000ull, 0x0000000000020000ull },
	{ NPU_NTL,         5, 0x000603ec03120000ull, 0x0000000000020000ull },
	{ NPU_NTL,         6, 0x000603ec03140000ull, 0x0000000000020000ull },
	{ NPU_NTL,         7, 0x000603ec03160000ull, 0x0000000000020000ull },
	{ NPU_GENID,       1, 0x000603ec03180000ull, 0x0000000000080000ull },
	{ NPU_NTL,         8, 0x000603ec03200000ull, 0x0000000000020000ull },
	{ NPU_NTL,         9, 0x000603ec03220000ull, 0x0000000000020000ull },
	{ NPU_NTL,        10, 0x000603ec03240000ull, 0x0000000000020000ull },
	{ NPU_NTL,        11, 0x000603ec03260000ull, 0x0000000000020000ull },
	{ NPU_GENID,       2, 0x000603ec03280000ull, 0x0000000000080000ull },
	{ RESV,            6, 0x000603ec03300000ull, 0x0000000ffcd00000ull },
	{ XSCOM,           0, 0x000603fc00000000ull, 0x0000000400000000ull },

	/* NULL entry at end */
	{ NULL_MAP, 0, 0, 0 },
};

static const struct phys_map_info phys_map_axone = {
	.chip_select_shift = 42,
	.table = phys_map_table_axone,
};

static inline bool phys_map_entry_null(const struct phys_map_entry *e)
{
	if (e->type == NULL_MAP)
		return true;
	return false;
}


/* This crashes skiboot on error as any bad calls here are almost
 *  certainly a developer error
 */
void phys_map_get(uint64_t gcid, enum phys_map_type type,
		  int index, uint64_t *addr, uint64_t *size) {
	const struct phys_map_entry *e;
	uint64_t a;

	if (!phys_map)
		goto error;

	/* Find entry in table */
	for (e = phys_map->table; ; e++) {

		/* End of table */
		if (phys_map_entry_null(e))
			goto error;

		/* Is this our entry? */
		if (e->type != type)
			continue;
		if (e->index != index)
			continue;

		/* Found entry! */
		break;
	}
	a = e->addr;
	a += gcid << phys_map->chip_select_shift;

	if (addr)
		*addr = a;
	if (size)
		*size = e->size;

	prlog(PR_TRACE, "Assigning BAR [%"PRIx64"] type:%02i index:%x "
	      "0x%016"PRIx64" for 0x%016"PRIx64"\n",
	      gcid, type, index, a, e->size);

	return;

error:
	/* Something has gone really wrong */
	prlog(PR_EMERG, "ERROR: Failed to lookup BAR type:%i index:%i\n",
	      type, index);
	assert(0);
}

void phys_map_init(unsigned long pvr)
{
	const char *name = "unused";

	phys_map = NULL;

	if (proc_gen == proc_gen_p9) {
		switch(PVR_TYPE(pvr)) {
		case PVR_TYPE_P9P:
			name = "axone";
			phys_map = &phys_map_axone;
			break;
		default:
			name = "nimbus";
			phys_map = &phys_map_nimbus;
		}
	}

	prlog(PR_DEBUG, "Assigning physical memory map table for %s\n", name);

}

